﻿using Api.Common;
using AppManager.BLL;
using AppManager.Model;
using Newtonsoft.Json.Linq;
using PushSharp.Apple;
using PushSharp.Core;
using PushSharp.Google;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PushTask
{
    internal class PushSharpSend
    {
        internal static void GcmSend(List<Message> list, List<MessageDevice> successList, List<MessageDevice> errorList)
        {
            if (list == null || list.Count() == 0) return;
            var project = list.FirstOrDefault().Project;

            //如果未配置使用gcm,直接返回
            if (!project.IsUseGcm) return;
            //如果配置錯誤返回
            if (project.GcmError) return;

            var senderId = project.SenderId;
            var authorizationToken = project.Token;
            var packageName = project.PackageName;

            //这个项目相关的所有消息，所有设备的总和
            var allDevices = list.Select(s => s.Devices).Aggregate(
                (f, s) =>
                {
                    f.AddRange(s); return f;
                }).Where(s => s.DeviceType == DeviceType.android && s.IsUseGoogle);

            if (!string.IsNullOrEmpty(senderId) &&
                    !string.IsNullOrEmpty(authorizationToken) &&
                    !string.IsNullOrEmpty(packageName))
            {

            }
            else
            {
                errorList.AddRange(allDevices);
                LogHelper.WriteLongLog(LogType.gcmError, project.Identity + " 未设置Project表中参数");
                project.GcmError = true;
                ProjectBLL.Update(project);
                return;
            }

            GcmConfiguration config = null;
            try
            {
                #region 启动服务

                try
                {
                    config = new GcmConfiguration(
                            senderId,
                            authorizationToken,
                            packageName);
                }
                catch (Exception ex)
                {
                    project.GcmError = true;
                    ProjectBLL.Update(project);
                    LogHelper.WriteLongLog("gcm配置錯誤" + project.Identity, ex.Message);
                }

                var gcmBroker = new GcmServiceBroker(config);

                gcmBroker.OnNotificationFailed += (notification, aggregateEx) =>
                {
                    Exception exception = null;
                    aggregateEx.Handle(ex =>
                    {
                        if (ex is GcmNotificationException)
                        {
                            var nofificationException = (GcmNotificationException)ex;

                            var gcmNotification = nofificationException.Notification;
                            var description = nofificationException.Description;
                        }
                        else if (ex is GcmMulticastResultException)
                        {

                        }
                        //else if (ex is MessageDeviceSubscriptionExpiredException)
                        //{
                        //    var expiredException = (MessageDeviceSubscriptionExpiredException)ex;
                        //    var oldId = expiredException.OldSubscriptionId;
                        //    var newId = expiredException.NewSubscriptionId;

                        //    if (!string.IsNullOrEmpty(newId))
                        //    {
                        //        //设备的订阅Id改变了
                        //    }
                        //}
                        else if (ex is RetryAfterException)
                        {
                            //如果是这个错误，你需要停止发送消息，直到 重试时间，就是在重试时间之前没有办法发送了
                        }
                        exception = ex;
                        //指定该异常已处理
                        return true;
                    });
                    Notification(notification, false, exception);
                };

                gcmBroker.OnNotificationSucceeded += (notification) =>
                {
                    Notification(notification, true);
                };
                gcmBroker.Start();
                #endregion

                #region 发消息
                foreach (var m in list)
                {
                    var devices = m.Devices.
                        Where(s => s.DeviceType == DeviceType.android && s.IsUseGoogle).
                        Where(s => !string.IsNullOrEmpty(s.DeviceStr));

                    var str = new AndroidData(m.Content, m.Data).ToString();

                    foreach (var item in devices)
                    {
                        try
                        {
                            gcmBroker.QueueNotification(new GcmNotification
                            {
                                RegistrationIds = new List<string> { item.DeviceStr },
                                Data = JObject.Parse(str),
                                Tag = m.Id
                            });
                        }
                        catch (Exception ex)
                        {
                            LogHelper.WriteLongLog(LogType.gcmError, ex.Message);
                            errorList.Add(item);
                        }
                        successList.Add(item);
                    }
                }
                #endregion

                gcmBroker.Stop();
            }
            catch (Exception ex)
            {
                LogHelper.WriteLongLog(LogType.gcmError, "GcmSend中發生異常" + ex.Message);
                errorList.AddRange(allDevices);
            }
        }

        internal static void ApnsSend(string path, List<Message> list, List<MessageDevice> successList, List<MessageDevice> errorList)
        {
            if (list == null || list.Count() == 0) return;
            var project = list.FirstOrDefault().Project;

            //如果該項目未配置使用apns,直接返回
            if (!project.IsUseApns) return;

            //如果ios配置發生錯誤,直接返回
            if (project.ApnsError) return;

            string certpath = "", certpwd = "";
            ApnsConfiguration config = null;

            //这个项目相关的所有消息，所有设备的总和

            var allDevices = list.Select(s => s.Devices).Aggregate(
                (f, s) =>
                {
                    f.AddRange(s); return f;
                }).Where(s => s.DeviceType == DeviceType.ios);

            try
            {
                try
                {
                    #region 配置开发版和正式版                
                    if (project.IsProduct)
                    {
                        certpath = path + project.CertUrl;
                        certpwd = project.CertPwd;
                        config = new ApnsConfiguration(
                            ApnsConfiguration.ApnsServerEnvironment.Production,
                            certpath,
                            certpwd);
                    }
                    else
                    {
                        certpath = path + project.SandBox_CertUrl;
                        certpwd = project.SandBox_CertPwd;

                        config = new ApnsConfiguration(
                            ApnsConfiguration.ApnsServerEnvironment.Sandbox,
                            certpath,
                            certpwd);
                    }
                    #endregion
                }
                catch (Exception ex)
                {
                    project.ApnsError = true;
                    ProjectBLL.Update(project);
                    LogHelper.WriteLongLog("apns配置錯誤" + project.Identity, project.Identity + ex.Message);
                }

                #region 如果项目配置失败，为所有的设备都添加失败记录
                if (!string.IsNullOrEmpty(certpath) &&
                                !string.IsNullOrEmpty(certpwd))
                {

                    if (!File.Exists(certpath))
                    {
                        errorList.AddRange(allDevices);
                        LogHelper.WriteLongLog(LogType.apnsError, project.Identity + " 证书不存在");
                        return;
                    }
                }
                else
                {
                    errorList.AddRange(allDevices);
                    LogHelper.WriteLongLog(LogType.apnsError, project.Identity + " 未设置证书或密码");
                    return;
                }
                #endregion

                #region 启动服务
                var broker = new ApnsServiceBroker(config);
                broker.OnNotificationFailed += (notification, exception) =>
                {
                    Notification(notification, false, exception);
                };
                broker.OnNotificationSucceeded += (notification) =>
                {
                    Notification(notification, true);
                };
                broker.Start();
                #endregion

                foreach (var m in list)
                {
                    var devices = m.Devices.
                        Where(s => s.DeviceType == DeviceType.ios).
                        Where(s => !string.IsNullOrEmpty(s.DeviceStr));
                    try
                    {
                        #region 发送消息                                                        
                        foreach (var item in devices)
                        {
                            try
                            {
                                //输入的格式必须是
                                var str = new IosData(m.Content, m.Data).ToString();

                                broker.QueueNotification(new ApnsNotification
                                {
                                    DeviceToken = item.DeviceStr.Trim(' ').Replace(" ", string.Empty),
                                    Payload = JObject.Parse(str),
                                    Tag = m.Id,
                                });
                            }
                            catch (Exception ex)
                            {
                                LogHelper.WriteLongLog(LogType.apnsError, ex.Message);
                                errorList.Add(item);
                            }
                            successList.Add(item);
                        }
                        #endregion
                    }
                    catch (Exception ex)
                    {
                        LogHelper.WriteLongLog(LogType.apnsError, "ApnsSend中循环list发生错误：" + ex.Message);
                        errorList.AddRange(devices);
                    }
                }

                broker.Stop();
            }
            catch (Exception ex)
            {
                LogHelper.WriteLongLog(LogType.apnsError, "在ApnsSend中執行發生錯誤：" + ex.Message);
                errorList.AddRange(allDevices);
            }
        }

        //public static void ApnsSend(string path, Project project, Message message, IEnumerable<MessageDevice> devices,
        //    List<MessageDevice> successList, List<MessageDevice> errorList)
        //{
        //    if (devices.Count() == 0) return;
        //    try
        //    {
        //        string certpath, certpwd;
        //        ApnsConfiguration config;

        //        certpath = path + project.CertUrl;
        //        certpwd = project.CertPwd;
        //        config = new ApnsConfiguration(
        //            ApnsConfiguration.ApnsServerEnvironment.Production,
        //            certpath,
        //            certpwd);

        //        if (!string.IsNullOrEmpty(certpath) &&
        //                    !string.IsNullOrEmpty(certpwd))
        //        {

        //            if (!File.Exists(certpath))
        //            {
        //                errorList.AddRange(devices);
        //                LogHelper.WriteLog(project.Identity + " 证书不存在");
        //                return;
        //            }
        //            else
        //            {
        //                #region 发送消息
        //                var broker = new ApnsServiceBroker(config);
        //                broker.OnNotificationFailed += (notification, exception) =>
        //                {
        //                    Notification(notification, false, exception);
        //                };
        //                broker.OnNotificationSucceeded += (notification) =>
        //                {
        //                    Notification(notification, true);
        //                };
        //                broker.Start();

        //                devices = from a in devices where !string.IsNullOrEmpty(a.DeviceStr) select a;
        //                foreach (var item in devices)
        //                {
        //                    try
        //                    {
        //                        //输入的格式必须是
        //                        var str = new IosData(message.Content, message.Data).ToString();

        //                        broker.QueueNotification(new ApnsNotification
        //                        {
        //                            DeviceToken = item.DeviceStr.Trim(' ').Replace(" ", string.Empty),
        //                            Payload = JObject.Parse(str),
        //                            Tag = message.Id,
        //                        });
        //                    }
        //                    catch (Exception ex)
        //                    {
        //                        LogHelper.WriteLog(ex.Message);
        //                        errorList.Add(item);
        //                    }
        //                    successList.Add(item);
        //                }

        //                broker.Stop();
        //                #endregion
        //            }

        //        }
        //        else
        //        {
        //            errorList.AddRange(devices);
        //            LogHelper.WriteLog(project.Identity + " 未设置证书或密码");
        //            return;
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        LogHelper.WriteLog("在ApnsSend中執行發生錯誤：" + ex.Message);
        //        errorList.AddRange(devices);
        //    }
        //}

        //public static void GcmSend(Project project, Message message,
        //    IEnumerable<MessageDevice> devices, List<MessageDevice> successList, List<MessageDevice> errorList)
        //{
        //    if (devices.Count() == 0) return;
        //    try
        //    {
        //        var senderId = project.SenderId;
        //        var authorizationToken = project.Token;
        //        var packageName = project.PackageName;

        //        if (!string.IsNullOrEmpty(senderId) &&
        //            !string.IsNullOrEmpty(authorizationToken) &&
        //            !string.IsNullOrEmpty(packageName))
        //        {

        //        }
        //        else
        //        {
        //            errorList.AddRange(devices);
        //            LogHelper.WriteLog(project.Identity + " 未设置Project表中参数");
        //            return;
        //        }

        //        var config = new GcmConfiguration(
        //            senderId,
        //            authorizationToken,
        //            packageName);

        //        var gcmBroker = new GcmServiceBroker(config);

        //        gcmBroker.OnNotificationFailed += (notification, aggregateEx) =>
        //        {
        //            Exception exception = null;
        //            aggregateEx.Handle(ex =>
        //            {
        //                if (ex is GcmNotificationException)
        //                {
        //                    var nofificationException = (GcmNotificationException)ex;

        //                    var gcmNotification = nofificationException.Notification;
        //                    var description = nofificationException.Description;
        //                }
        //                else if (ex is GcmMulticastResultException)
        //                {

        //                }
        //                //else if (ex is MessageDeviceSubscriptionExpiredException)
        //                //{
        //                //    var expiredException = (MessageDeviceSubscriptionExpiredException)ex;
        //                //    var oldId = expiredException.OldSubscriptionId;
        //                //    var newId = expiredException.NewSubscriptionId;

        //                //    if (!string.IsNullOrEmpty(newId))
        //                //    {
        //                //        //设备的订阅Id改变了
        //                //    }
        //                //}
        //                else if (ex is RetryAfterException)
        //                {
        //                    //如果是这个错误，你需要停止发送消息，直到 重试时间，就是在重试时间之前没有办法发送了
        //                }
        //                exception = ex;
        //                //指定该异常已处理
        //                return true;
        //            });
        //            Notification(notification, false, exception);
        //        };

        //        gcmBroker.OnNotificationSucceeded += (notification) =>
        //        {
        //            Notification(notification, true);
        //        };
        //        gcmBroker.Start();

        //        devices = from a in devices where !string.IsNullOrEmpty(a.DeviceStr) select a;
        //        foreach (var item in devices)
        //        {
        //            try
        //            {
        //                var str = new AndroidData(message.Content, message.Data).ToString();

        //                gcmBroker.QueueNotification(new GcmNotification
        //                {
        //                    RegistrationIds = new List<string> { item.DeviceStr },
        //                    Data = JObject.Parse(str),
        //                    Tag = message.Id
        //                });
        //            }
        //            catch (Exception ex)
        //            {
        //                LogHelper.WriteLog(ex.Message);
        //                errorList.Add(item);
        //            }
        //            successList.Add(item);
        //        }
        //        gcmBroker.Stop();
        //    }
        //    catch (Exception ex)
        //    {
        //        LogHelper.WriteLog("GcmSend中發生異常" + ex.Message);
        //    }
        //}

        /// <summary>
        /// 处理返回数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="notification"></param>
        /// <param name="isSuccess"></param>
        private static void Notification(INotification notification, bool isSuccess, Exception ex = null)
        {
            try
            {
                string devicetoken = "";
                int mId = 0;
                string message = string.Empty;
                if (notification is ApnsNotification)
                {
                    var notify = (ApnsNotification)notification;
                    devicetoken = notify?.DeviceToken;
                    int.TryParse(notify?.Tag?.ToString(), out mId);
                    if (ex != null)
                    {
                        DisplayException(ex, ref message);
                    }
                }
                else if (notification is GcmNotification)
                {
                    var gcmNotify = (GcmNotification)notification;
                    devicetoken = gcmNotify?.RegistrationIds[0];
                    int.TryParse(gcmNotify?.Tag?.ToString(), out mId);
                    if (ex != null)
                    {
                        DisplayException(ex, ref message);
                    }
                }
                MessageDeviceBLL.UpdateRemoteServer(isSuccess, mId, devicetoken, message);
            }
            catch (Exception exception)
            {
                LogHelper.WriteLongLog(LogType.notify, "Notification中發生異常" + exception.Message);
            }
        }

        private static void DisplayException(Exception ex, ref string msg)
        {
            if (ex != null)
            {
                msg += ex.Message + Environment.NewLine;
                DisplayException(ex.InnerException, ref msg);
            }
        }
    }
}
